#include "syntax_parser.h"
#include "errors_warnings.h"

#include "main_container.h"
extern MainContainer * CompilerData;


// <value> ~ LITERAL  {LITERAL}
// <value> ~ null  {null}
// <value> ~ new <data_type> <array_definitions_size> ( <arguments> )  {new}
// <value> ~ new <data_type> <array_definitions_size> <initialisation>  {new}
// <value> ~ <name> instance of <name>  {NAME}
// <value> ~ NAME ( <arguments> )  {NAME}
// <value> ~ ( <expression> )  {(}
// <value> ~ ( data_type ) <variable_value>  {(}
// <value> ~ <variable_value>  {NAME}
// <value> ~ <variable_value> . NAME ( <arguments> )  {NAME}
void Parser::Parse_Value(SyntaxTreeNode * parent)
{
#ifdef TRACE
	CompilerData->LogTrace->ReportEntry("Parse_Value");
#endif
	LexicUnit currentUnit;
	LexicUnit nextUnit;
	LexicUnit precedingUnit;
	
#ifdef TRACE
	CompilerData->LogTrace->ReportLine("Getting lexic unit.");
#endif
	// get current lexic unit
	currentUnit = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition);
	// get next lexic unit
	nextUnit = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition + 1);
	// get preceding lexic unit
	precedingUnit = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition - 1);

	int error = -1;
	int chouseProduction = -1;
	int lexicPosition = this->CurrentLexicPosition;

	// if current lexic unit is in the select set of {LITERAL}
	if(currentUnit.type==LUTypeConstantBool || currentUnit.type==LUTypeConstantFloat || currentUnit.type==LUTypeConstantInteger)
	{
#ifdef TRACE
		CompilerData->LogTrace->ReportLine("Recognized keyword \"LITERAL\"");
#endif
		// write type of production in this node
		parent->Production = Gr_Value__LITERAL;

		// process terminal symbol 'LITERAL' 
		SyntaxTreeNode * newNode0 = new SyntaxTreeNode();
		parent->Nodes->Add(newNode0);
		newNode0->LexUnitID=this->CurrentLexicPosition;
		newNode0->Production=Gr_Terminal;
		//increase counter
		CurrentLexicPosition++;

	}
	// if current lexic unit is in the select set of {null}
	else if(currentUnit.type == LUTypeKeyword && currentUnit.subtype == KeywordNull)
	{
#ifdef TRACE
		CompilerData->LogTrace->ReportLine("Recognized keyword \"null\"");
#endif
		// write type of production in this node
		parent->Production = Gr_Value__null;

		// process terminal symbol 'null' 
		SyntaxTreeNode * newNode0 = new SyntaxTreeNode();
		parent->Nodes->Add(newNode0);
		newNode0->LexUnitID=this->CurrentLexicPosition;
		newNode0->Production=Gr_Terminal;
		//increase counter
		CurrentLexicPosition++;

	}
	// if current lexic unit is in the select set of {new}
	else if(currentUnit.type == LUTypeKeyword && currentUnit.subtype == KeywordNew)
	{
#ifdef TRACE
		CompilerData->LogTrace->ReportLine("Recognized keyword \"new\"");
#endif
		// process terminal symbol 'new' 
		SyntaxTreeNode * newNode0 = new SyntaxTreeNode();
		parent->Nodes->Add(newNode0);
		newNode0->LexUnitID=this->CurrentLexicPosition;
		newNode0->Production=Gr_Terminal;
		//increase counter
		CurrentLexicPosition++;

		// process nonterminal symbol <data_type>
		SyntaxTreeNode * newNode1 = new SyntaxTreeNode();
		parent->Nodes->Add(newNode1);
		Parse_DataType(newNode1);

		// process nonterminal symbol <array_definitions_size> 
		SyntaxTreeNode * newNode2 = new SyntaxTreeNode();
		parent->Nodes->Add(newNode2);
		Parse_ArrayDefinitionsSize(newNode2);
		
		currentUnit = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition);
		if(currentUnit.type == LUTypeSpecialCharacter && currentUnit.subtype == SpecialCharacterLeftParenthesis)
		{

#ifdef TRACE
		CompilerData->LogTrace->ReportLine("Recognized special character \"(\"");
#endif
			// write type of production in this node
			parent->Production = Gr_Value__new_DataType_ArrayDefinitionsSize_spLPar_Arguments_spRPar;

			// process terminal symbol '(' 
			SyntaxTreeNode * newNode3 = new SyntaxTreeNode();
			parent->Nodes->Add(newNode3);
			newNode3->LexUnitID=this->CurrentLexicPosition;
			newNode3->Production=Gr_Terminal;
			//increase counter
			CurrentLexicPosition++;

			// process nonterminal symbol <arguments> 
			SyntaxTreeNode * newNode4 = new SyntaxTreeNode();
			parent->Nodes->Add(newNode4);
			Parse_Arguments(newNode4);

			// process terminal symbol ')' 
			currentUnit = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition);
			if(currentUnit.type == LUTypeSpecialCharacter && currentUnit.subtype == SpecialCharacterRightParenthesis)
			{
#ifdef TRACE
		CompilerData->LogTrace->ReportLine("Recognized special character \")\"");
#endif
				SyntaxTreeNode * newNode5 = new SyntaxTreeNode();
				parent->Nodes->Add(newNode5);
				newNode5->LexUnitID=this->CurrentLexicPosition;
				newNode5->Production=Gr_Terminal;
				//increase counter
				CurrentLexicPosition++;
			}
			else
			{
				//report syntactic error
				CompilerData->ErrorWarningReport->ReportError(&currentUnit, ERR_SYN_NO_RIGHT_PARENTHESIS_MATCH);
				//increase counter
				CurrentLexicPosition++;
			}
		}
		else
		{
			// write type of production in this node
			parent->Production = Gr_Value__new_DataType_ArrayDefinitionsSize_Initialisation;

			// process nonterminal symbol <initialisation> 
			SyntaxTreeNode * newNode3 = new SyntaxTreeNode();
			parent->Nodes->Add(newNode3);
			Parse_Initialisation(newNode3);
		}
	}
	// if current lexic unit is in the select set of {NAME}
	else if(currentUnit.type == LUTypeIdentifier)
	{
#ifdef TRACE
		CompilerData->LogTrace->ReportLine("Recognized keyword \"NAME\"");
#endif		
		if(nextUnit.type == LUTypeSpecialCharacter && nextUnit.subtype == SpecialCharacterLeftParenthesis)
		{
			// write type of production in this node
			parent->Production = Gr_Value__NAME_spLPar_Arguments_spRPar;

#ifdef TRACE
		CompilerData->LogTrace->ReportLine("Recognized special character \"(\"");
#endif	

			// process terminal symbol 'NAME' 
			SyntaxTreeNode * newNode0 = new SyntaxTreeNode();
			parent->Nodes->Add(newNode0);
			newNode0->LexUnitID=this->CurrentLexicPosition;
			newNode0->Production=Gr_Terminal;
			//increase counter
			CurrentLexicPosition++;

			// process terminal symbol '(' 
			SyntaxTreeNode * newNode1 = new SyntaxTreeNode();
			parent->Nodes->Add(newNode1);
			newNode1->LexUnitID=this->CurrentLexicPosition;
			newNode1->Production=Gr_Terminal;
			//increase counter
			CurrentLexicPosition++;
			
			// process nonterminal symbol <arguments> 
			SyntaxTreeNode * newNode2 = new SyntaxTreeNode();
			parent->Nodes->Add(newNode2);
			Parse_Arguments(newNode2);

			// process terminal symbol ')' 
			currentUnit = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition);
			if(currentUnit.type == LUTypeSpecialCharacter && currentUnit.subtype == SpecialCharacterRightParenthesis)
			{

#ifdef TRACE
		CompilerData->LogTrace->ReportLine("Recognized special character \")\"");
#endif
				SyntaxTreeNode * newNode3 = new SyntaxTreeNode();
				parent->Nodes->Add(newNode3);
				newNode3->LexUnitID=this->CurrentLexicPosition;
				newNode3->Production=Gr_Terminal;
				//increase counter
				CurrentLexicPosition++;
			}
			else
			{
				//report syntactic error
				CompilerData->ErrorWarningReport->ReportError(&currentUnit, ERR_SYN_NO_RIGHT_PARENTHESIS_MATCH);
				//increase counter
				CurrentLexicPosition++;
			}


		}
		else
		{
			
			do
			{
				// get lexic unit
				currentUnit = CompilerData->Units->GetLexicUnit(lexicPosition + 1);
				nextUnit = CompilerData->Units->GetLexicUnit(lexicPosition + 2);

				if(currentUnit.type == LUTypeSpecialCharacter && currentUnit.subtype == SpecialCharacterSemicolon)
				{
					break;
				}

				// if lexic unit is endOfFile
				if((currentUnit.type == LUTypeSpecialType && currentUnit.subtype == endOfFile)
					||(nextUnit.type == LUTypeSpecialType && nextUnit.subtype == endOfFile))
				{
					error = 1;
					break;
				}
				
				else if(
					(currentUnit.type == LUTypeSpecialCharacter && currentUnit.subtype == SpecialCharacterPeriod) &&
					(nextUnit.type == LUTypeIdentifier)
					)
				{
					lexicPosition += 2;
					continue;
				}
				else
				{
					break;
				}

				
			}
			while(1);

			if(error != 1)
			{

				if(currentUnit.type == LUTypeKeyword && currentUnit.subtype == KeywordInstance)
				{
					// write type of production in this node
					parent->Production = Gr_Value__Name_instance_of_Name;

					// process nonterminal symbol <name> 
					SyntaxTreeNode * newNode0 = new SyntaxTreeNode();
					parent->Nodes->Add(newNode0);
					Parse_Name(newNode0);

#ifdef TRACE
		CompilerData->LogTrace->ReportLine("Recognized keyword \"instance\"");
#endif

					// process terminal symbol 'instance' 
					SyntaxTreeNode * newNode1 = new SyntaxTreeNode();
					parent->Nodes->Add(newNode1);
					newNode1->LexUnitID=this->CurrentLexicPosition;
					newNode1->Production=Gr_Terminal;
					//increase counter
					CurrentLexicPosition++;
					

					// process terminal symbol 'of' 
					currentUnit = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition);
					if(currentUnit.type == LUTypeKeyword && currentUnit.subtype == KeywordOf)
					{
#ifdef TRACE
		CompilerData->LogTrace->ReportLine("Recognized keyword \"of\"");
#endif
						SyntaxTreeNode * newNode2 = new SyntaxTreeNode();
						parent->Nodes->Add(newNode2);
						newNode2->LexUnitID=this->CurrentLexicPosition;
						newNode2->Production=Gr_Terminal;
						//increase counter
						CurrentLexicPosition++;
					}
					else
					{
						//report syntactic error
						CompilerData->ErrorWarningReport->ReportError(&currentUnit, ERR_SYN_NO_KEYWORD_OF_MATCH);
						//increase counter
						CurrentLexicPosition++;
					}

					// process nonterminal symbol <name> 
					SyntaxTreeNode * newNode3 = new SyntaxTreeNode();
					parent->Nodes->Add(newNode3);
					Parse_Name(newNode3);
				}
				else
				{
					// process nonterminal symbol <variable_value> 
					SyntaxTreeNode * newNode0 = new SyntaxTreeNode();
					parent->Nodes->Add(newNode0);
					Parse_VariableValue(newNode0);

					currentUnit = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition);
					nextUnit = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition + 1);

					if(
						(currentUnit.type == LUTypeSpecialCharacter && currentUnit.subtype == SpecialCharacterPeriod) &&
						(nextUnit.type == LUTypeIdentifier)
						)
					{
						// write type of production in this node
						parent->Production = Gr_Value__VariableValue_spPer_NAME_spLPar_Arguments_spRPar;
#ifdef TRACE
		CompilerData->LogTrace->ReportLine("Recognized special character \".\"");
#endif
						// process terminal symbol '.' 
						SyntaxTreeNode * newNode1 = new SyntaxTreeNode();
						parent->Nodes->Add(newNode1);
						newNode1->LexUnitID=this->CurrentLexicPosition;
						newNode1->Production=Gr_Terminal;
						//increase counter
						CurrentLexicPosition++;

#ifdef TRACE
		CompilerData->LogTrace->ReportLine("Recognized keyword \"NAME\"");
#endif

						// process terminal symbol 'NAME' 
						SyntaxTreeNode * newNode2 = new SyntaxTreeNode();
						parent->Nodes->Add(newNode2);
						newNode2->LexUnitID=this->CurrentLexicPosition;
						newNode2->Production=Gr_Terminal;
						//increase counter
						CurrentLexicPosition++;
						

						// process terminal symbol '(' 
						currentUnit = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition);
						if(currentUnit.type == LUTypeSpecialCharacter && currentUnit.subtype == SpecialCharacterLeftParenthesis)
						{
#ifdef TRACE
		CompilerData->LogTrace->ReportLine("Recognized special character \"(\"");
#endif
							SyntaxTreeNode * newNode3 = new SyntaxTreeNode();
							parent->Nodes->Add(newNode3);
							newNode3->LexUnitID=this->CurrentLexicPosition;
							newNode3->Production=Gr_Terminal;
							//increase counter
							CurrentLexicPosition++;
						}
						else
						{
							//report syntactic error
							CompilerData->ErrorWarningReport->ReportError(&currentUnit, ERR_SYN_NO_LEFT_PARENTHESIS_MATCH);
							//increase counter
							CurrentLexicPosition++;
						}

						// process nonterminal symbol <arguments> 
						SyntaxTreeNode * newNode4 = new SyntaxTreeNode();
						parent->Nodes->Add(newNode4);
						Parse_Arguments(newNode4);

						// process terminal symbol ')' 
						currentUnit = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition);
						if(currentUnit.type == LUTypeSpecialCharacter && currentUnit.subtype == SpecialCharacterRightParenthesis)
						{
#ifdef TRACE
		CompilerData->LogTrace->ReportLine("Recognized special character \")\"");
#endif
							SyntaxTreeNode * newNode5 = new SyntaxTreeNode();
							parent->Nodes->Add(newNode5);
							newNode5->LexUnitID=this->CurrentLexicPosition;
							newNode5->Production=Gr_Terminal;
							//increase counter
							CurrentLexicPosition++;
						}
						else
						{
							//report syntactic error
							CompilerData->ErrorWarningReport->ReportError(&currentUnit, ERR_SYN_NO_RIGHT_PARENTHESIS_MATCH);
							//increase counter
							CurrentLexicPosition++;
						}
					}
					else
					{
						// write type of production in this node
						parent->Production = Gr_Value__VariableValue;
					}
				}
			}
			else
			{
				// ERROR has been found
				// REPORT ERROR
				CompilerData->ErrorWarningReport->ReportError(&currentUnit, ERR_SYN_NO_UNEXPECTED_END_OF_FILE);
				// This is recovoring from error
				this->CurrentLexicPosition++;
			}
		}
	}
	// if current lexic unit is in the select set of {(}
	else if(currentUnit.type == LUTypeSpecialCharacter && currentUnit.subtype == SpecialCharacterLeftParenthesis)
	{
#ifdef TRACE
		CompilerData->LogTrace->ReportLine("Recognized keyword \"(\"");
#endif	
		// process terminal symbol '(' 
		SyntaxTreeNode * newNode0 = new SyntaxTreeNode();
		parent->Nodes->Add(newNode0);
		newNode0->LexUnitID=this->CurrentLexicPosition;
		newNode0->Production=Gr_Terminal;
		//increase counter
		CurrentLexicPosition++;

		currentUnit = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition);

		if(currentUnit.type == LUTypeIdentifier)
		{

			lexicPosition = this->CurrentLexicPosition;
			do
			{
				// get lexic unit
				currentUnit = CompilerData->Units->GetLexicUnit(lexicPosition + 1);
				nextUnit = CompilerData->Units->GetLexicUnit(lexicPosition + 2);
				
				// if lexic unit is endOfFile
				if(currentUnit.type == LUTypeSpecialType && currentUnit.subtype == endOfFile)
				{
					error = 1;
					break;
				}
				
				else if(
					(currentUnit.type == LUTypeSpecialCharacter && currentUnit.subtype == SpecialCharacterPeriod) &&
                    (nextUnit.type == LUTypeIdentifier)
					)
				{
					lexicPosition += 2;
					continue;
				}
				else
				{
					break;
				}
				
			}
			while(1);
	
			if(
				(currentUnit.type == LUTypeSpecialCharacter && currentUnit.subtype == SpecialCharacterRightParenthesis) &&
                (nextUnit.type == LUTypeIdentifier)
				)
				{
					
					if(precedingUnit.type == LUTypeKeyword && precedingUnit.subtype == KeywordUpto)
					{
						chouseProduction = 1;
					}
					else
					{
						chouseProduction = 2;
					}	
				}

			else
			{
				chouseProduction = 1;
			}
		}
		else if(currentUnit.type==LUTypeKeyword &&
         (currentUnit.subtype ==KeywordInt || currentUnit.subtype ==KeywordFloat ||
          currentUnit.subtype ==KeywordBool || currentUnit.subtype ==KeywordState ||
          currentUnit.subtype ==KeywordTime || currentUnit.subtype ==KeywordVoid ||
          currentUnit.subtype ==KeywordFacility || currentUnit.subtype ==KeywordStorage ||
          currentUnit.subtype ==KeywordQueue || currentUnit.subtype ==KeywordADTable ||
          currentUnit.subtype ==KeywordGroup || currentUnit.subtype ==KeywordOutputStream)
         )
      {
         chouseProduction = 2;
      }
      else
		{
			chouseProduction = 1;
		}
		
		if(error != 1)
		{
			// get current lexic unit
			currentUnit = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition);
	
			if(chouseProduction == 1)
			{

				// write type of production in this node
				parent->Production = Gr_Value__spLPar_Expression_spRPar;

				// process nonterminal symbol <expression> 
				SyntaxTreeNode * newNode1 = new SyntaxTreeNode();
				parent->Nodes->Add(newNode1);
				Parse_Expression(newNode1);

				// process terminal symbol ')' 
				currentUnit = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition);
				if(currentUnit.type == LUTypeSpecialCharacter && currentUnit.subtype == SpecialCharacterRightParenthesis)
				{
#ifdef TRACE
		CompilerData->LogTrace->ReportLine("Recognized special character \")\"");
#endif
					SyntaxTreeNode * newNode2 = new SyntaxTreeNode();
					parent->Nodes->Add(newNode2);
					newNode2->LexUnitID=this->CurrentLexicPosition;
					newNode2->Production=Gr_Terminal;
					//increase counter
					CurrentLexicPosition++;
				}
				else
				{
					//report syntactic error
					CompilerData->ErrorWarningReport->ReportError(&currentUnit, ERR_SYN_NO_RIGHT_PARENTHESIS_MATCH);
					//increase counter
					CurrentLexicPosition++;
				}
			}
			else
			{

				// write type of production in this node
				parent->Production = Gr_Value__spLPar_DataType_spRPar_VariableValue;

				// process nonterminal symbol <data_type> 
				SyntaxTreeNode * newNode1 = new SyntaxTreeNode();
				parent->Nodes->Add(newNode1);
				Parse_DataType(newNode1);

				// process terminal symbol ')' 
				currentUnit = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition);
				if(currentUnit.type == LUTypeSpecialCharacter && currentUnit.subtype == SpecialCharacterRightParenthesis)
				{
#ifdef TRACE
		CompilerData->LogTrace->ReportLine("Recognized special character \")\"");
#endif
					SyntaxTreeNode * newNode2 = new SyntaxTreeNode();
					parent->Nodes->Add(newNode2);
					newNode2->LexUnitID=this->CurrentLexicPosition;
					newNode2->Production=Gr_Terminal;
					//increase counter
					CurrentLexicPosition++;
				}
				else
				{
					//report syntactic error
					CompilerData->ErrorWarningReport->ReportError(&currentUnit, ERR_SYN_NO_RIGHT_PARENTHESIS_MATCH);
					//increase counter
					CurrentLexicPosition++;
				}

				// process nonterminal symbol <variable_value> 
				SyntaxTreeNode * newNode3 = new SyntaxTreeNode();
				parent->Nodes->Add(newNode3);
				Parse_VariableValue(newNode3);

			}

		}
		else
		{
			// ERROR has been found
			// REPORT ERROR
			CompilerData->ErrorWarningReport->ReportError(&currentUnit, ERR_SYN_NO_UNEXPECTED_END_OF_FILE);
			// This is recovoring from error
			this->CurrentLexicPosition++;
		}
	}

	else
	{
		// ERROR has been found
		// REPORT ERROR
		CompilerData->ErrorWarningReport->ReportError(&currentUnit, ERR_SYN_NO_VALUE_BEGINING);
		// This is recovoring from error
        this->CurrentLexicPosition++;
	}
#ifdef TRACE
	CompilerData->LogTrace->ReportExit("Parse_Value");
#endif

}


// <variable_value> ~ <name_ambiguous> <array_definitions_size> <variable_value_add>  {NAME}
void Parser::Parse_VariableValue(SyntaxTreeNode * parent)
{
#ifdef TRACE
	CompilerData->LogTrace->ReportEntry("Parse_VariableValue");
#endif	
	LexicUnit currentUnit;

#ifdef TRACE
	CompilerData->LogTrace->ReportLine("Getting lexic unit.");
#endif
	// get current lexic unit
	currentUnit = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition);

	if(currentUnit.type == LUTypeIdentifier)
	{
		// write type of production in this node
		parent->Production = Gr_VariableValue__NameAmbiguous_ArrayDefinitionsSize_VariableValueAdd;

		// process nonterminal symbol <name> 
		SyntaxTreeNode * newNode0 = new SyntaxTreeNode();
		parent->Nodes->Add(newNode0);
		Parse_Name_Ambiguous(newNode0);

		// process nonterminal symbol <array_definitions_size> 
		SyntaxTreeNode * newNode1 = new SyntaxTreeNode();
		parent->Nodes->Add(newNode1);
		Parse_ArrayDefinitionsSize(newNode1);

		// process nonterminal symbol <variable_value_add> 
		SyntaxTreeNode * newNode2 = new SyntaxTreeNode();
		parent->Nodes->Add(newNode2);
		Parse_VariableValueAdd(newNode2);

	}


	else
	{
		// ERROR has been found
		// REPORT ERROR
		CompilerData->ErrorWarningReport->ReportError(&currentUnit, ERR_SYN_NO_VARIABLE_VALUE_BEGINING);
		// This is recovoring from error
		this->CurrentLexicPosition++;
	}
#ifdef TRACE
	CompilerData->LogTrace->ReportExit("Parse_VariableValue");
#endif
}


// <variable_value_add> ~ <period_variable_value> <variable_value_add>  {.}
// <variable_value_add> ~ ? {:,=, ., ^, *, /, %, +, -, <, >, <=, >=, ==, !=, &&, ^^, ||, ,, ;, ), +-, forming, units, {, simulations, ], NAME, after, every, send, while, until,}}
void Parser::Parse_VariableValueAdd(SyntaxTreeNode * parent)
{
#ifdef TRACE
	CompilerData->LogTrace->ReportEntry("Parse_VariableValueAdd");
#endif	
	LexicUnit currentUnit;
	LexicUnit firstNextUnit;
	LexicUnit secondNextUnit;


	do
	{
#ifdef TRACE
	CompilerData->LogTrace->ReportLine("Getting lexic unit.");
#endif
		// get current lexic unit
		currentUnit = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition);
		// get first next lexic unit
		firstNextUnit = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition + 1);
		// get second next lexic unit
		secondNextUnit = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition + 2);

		if(currentUnit.type == LUTypeSpecialCharacter && currentUnit.subtype == SpecialCharacterPeriod)
		{
			if(
				(firstNextUnit.type == LUTypeIdentifier) && 
				(secondNextUnit.type == LUTypeSpecialCharacter && secondNextUnit.subtype == SpecialCharacterLeftParenthesis)
				)
			{
				// epsilon production
				parent->Production = Gr_VariableValueAdd__PeriodVariableValue_VariableValueAdd;
				break;
			}
			else
			{
				// write type of production in this node
				parent->Production = Gr_VariableValueAdd__PeriodVariableValue_VariableValueAdd;

				// process nonterminal symbol <period_variable_value> 
				SyntaxTreeNode * newNode0 = new SyntaxTreeNode();
				parent->Nodes->Add(newNode0);
				Parse_PeriodVariableValue(newNode0);
			}
		}
		else if(
			(currentUnit.type == LUTypeOperator && currentUnit.subtype == OperatorAssigment) ||
			(currentUnit.type == LUTypeSpecialCharacter && currentUnit.subtype == SpecialCharacterPeriod) ||
			(currentUnit.type == LUTypeOperator && currentUnit.subtype == OperatorExponentiation) ||
			(currentUnit.type == LUTypeOperator && currentUnit.subtype == OperatorMultiplication) ||
			(currentUnit.type == LUTypeOperator && currentUnit.subtype == OperatorDivision) ||
			(currentUnit.type == LUTypeOperator && currentUnit.subtype == OperatorModulus) ||
			(currentUnit.type == LUTypeOperator && currentUnit.subtype == OperatorAddition) ||
			(currentUnit.type == LUTypeOperator && currentUnit.subtype == OperatorSubtraction) ||
			(currentUnit.type == LUTypeOperator && currentUnit.subtype == OperatorLessThan) ||
			(currentUnit.type == LUTypeOperator && currentUnit.subtype == OperatorGreaterThan) ||
			(currentUnit.type == LUTypeOperator && currentUnit.subtype == OperatorLessThanOrEqualTo) ||
			(currentUnit.type == LUTypeOperator && currentUnit.subtype == OperatorGreaterThanEqualTo) ||
			(currentUnit.type == LUTypeOperator && currentUnit.subtype == OperatorEqual) ||
			(currentUnit.type == LUTypeOperator && currentUnit.subtype == OperatorNotEqual) ||
			(currentUnit.type == LUTypeOperator && currentUnit.subtype == OperatorAnd) ||
			(currentUnit.type == LUTypeOperator && currentUnit.subtype == OperatorXor) ||
			(currentUnit.type == LUTypeOperator && currentUnit.subtype == OperatorOr) ||
			(currentUnit.type == LUTypeSpecialCharacter && currentUnit.subtype == SpecialCharacterComma) ||
			(currentUnit.type == LUTypeSpecialCharacter && currentUnit.subtype == SpecialCharacterSemicolon) ||
			(currentUnit.type == LUTypeSpecialCharacter && currentUnit.subtype == SpecialCharacterColon) ||
			(currentUnit.type == LUTypeSpecialCharacter && currentUnit.subtype == SpecialCharacterRightParenthesis) ||
			(currentUnit.type == LUTypeSpecialCharacter && currentUnit.subtype == SpecialCharacterPlusOrMinus) ||
			(currentUnit.type == LUTypeKeyword && currentUnit.subtype == KeywordForming) ||
			(currentUnit.type == LUTypeKeyword && currentUnit.subtype == KeywordUnits) ||
			(currentUnit.type == LUTypeSpecialCharacter && currentUnit.subtype == SpecialCharacterLeftCurlyBrace) ||(currentUnit.type == LUTypeSpecialCharacter && currentUnit.subtype == SpecialCharacterRightCurlyBrace) ||
			(currentUnit.type == LUTypeKeyword && currentUnit.subtype == KeywordSimulations) ||
			(currentUnit.type == LUTypeSpecialCharacter && currentUnit.subtype == SpecialCharacterRightSquareBracket) ||
			(currentUnit.type == LUTypeIdentifier) ||
			(currentUnit.type == LUTypeKeyword && currentUnit.subtype == KeywordAfter) ||
			(currentUnit.type == LUTypeKeyword && currentUnit.subtype == KeywordEvery) ||
			(currentUnit.type == LUTypeKeyword && currentUnit.subtype == KeywordSend) ||
			(currentUnit.type == LUTypeKeyword && currentUnit.subtype == KeywordWhile) ||
			(currentUnit.type == LUTypeKeyword && currentUnit.subtype == KeywordUntil)
			)
		{
			// this is epsilon part of production
			// new node is not needed
			// there are no symbols on the right side of this production
			// so that all
			parent->Production = Gr_VariableValueAdd__PeriodVariableValue_VariableValueAdd;
			break;

		}


		else
		{
			// ERROR has been found
			// REPORT ERROR
			CompilerData->ErrorWarningReport->ReportError(&currentUnit, ERR_SYN_NO_VARIABLE_VALUE_ADD_BEGINING);
			// This is recovoring from error
			this->CurrentLexicPosition++;
			break;
		}
	}
	while(1);
#ifdef TRACE
	CompilerData->LogTrace->ReportExit("Parse_VariableValueAdd");
#endif
}

// <period_variable_value> ~ . <variable_value>  {.}
void Parser::Parse_PeriodVariableValue(SyntaxTreeNode * parent)
{
#ifdef TRACE
	CompilerData->LogTrace->ReportEntry("Parse_PeriodVariableValue");
#endif
	LexicUnit currentUnit;
	// get current lexic unit
#ifdef TRACE
	CompilerData->LogTrace->ReportLine("Getting lexic unit.");
#endif
	currentUnit = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition);


	if(currentUnit.type == LUTypeSpecialCharacter && currentUnit.subtype == SpecialCharacterPeriod)
	{
		// write type of production in this node
		parent->Production = Gr_PeriodVariableValue__spPer_VariableValue;
#ifdef TRACE
		CompilerData->LogTrace->ReportLine("Recognized special character \".\"");
#endif
		// process terminal symbol '.' 
		SyntaxTreeNode * newNode0 = new SyntaxTreeNode();
		parent->Nodes->Add(newNode0);
		newNode0->LexUnitID=this->CurrentLexicPosition;
		newNode0->Production=Gr_Terminal;
		//increase counter
		CurrentLexicPosition++;

		// process nonterminal symbol <variable_value> 
		SyntaxTreeNode * newNode1 = new SyntaxTreeNode();
		parent->Nodes->Add(newNode1);
		Parse_VariableValue(newNode1);

	}


	else
	{
#ifdef TRACE
	CompilerData->LogTrace->ReportLine("Error. No recovery for now.");
#endif
		// ERROR has been found
		// REPORT ERROR
		CompilerData->ErrorWarningReport->ReportError(&currentUnit, ERR_SYN_NO_PERIOD_VARIABLE_VALUE_BEGINING);
		// This is recovoring from error
        this->CurrentLexicPosition++;
	}
#ifdef TRACE
	CompilerData->LogTrace->ReportExit("Parse_PeriodVariableValue");
#endif
}



